home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Speccy ClassiX 1998
/
Speccy ClassiX 98.iso
/
amiga_system
/
the_aminet
/
dev
/
gcc
/
ixemulsrc.lha
/
ixemul-41.4
/
library
/
stat.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-27
|
7KB
|
241 lines
/*
* This file is part of ixemul.library for the Amiga.
* Copyright (C) 1991, 1992 Markus M. Wild
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* stat.c,v 1.1.1.1 1994/04/04 04:30:35 amiga Exp
*
* stat.c,v
* Revision 1.1.1.1 1994/04/04 04:30:35 amiga
* Initial CVS check in.
*
* Revision 1.2 1993/11/05 22:03:10 mwild
* grp/oth support, plus new feature
*
* Revision 1.1 1992/05/14 19:55:40 mwild
* Initial revision
*
*/
#define KERNEL
#include "ixemul.h"
#include "kprintf.h"
#if __GNUC__ != 2
#define alloca __builtin_alloca
#endif
#ifndef ST_ROOT
#define ST_ROOT 1
#define ST_USERDIR 2
#define ST_SOFTLINK 3
#define ST_LINKDIR 4
#define ST_FILE -3
#define ST_LINKFILE -4
#endif
#ifndef ERROR_IS_SOFT_LINK
#define ERROR_IS_SOFT_LINK 233
#endif
/* currently, links are quite buggy.. hope this get cleaned up RSN ;-) */
extern BPTR __lock (), __llock ();
static int
__stat(char *fname, struct stat *stb, BPTR (*lock_func)())
{
BPTR lock;
long mode;
struct FileInfoBlock *fib;
struct InfoData *info;
int omask;
int error;
bzero (stb, sizeof(*stb));
omask = syscall (SYS_sigsetmask, ~0);
if (!(lock = (*lock_func) (fname, ACCESS_READ)))
{
int err = IoErr ();
/* take special care of NIL:, /dev/null and friends ;-) */
if (err == 4242)
{
stb->st_mode = S_IFCHR | 0777;
stb->st_nlink = 1;
stb->st_blksize = ix.ix_fs_buf_factor * 512;
stb->st_blocks = 0;
goto rest_sigmask;
}
KPRINTF (("__stat: lock %s failed, err = %ld.\n", fname, err));
if (err == ERROR_IS_SOFT_LINK)
{
/* provide some default stb.. we can't get anymore info than
* that. Symlinks should work with Lock(), but till now they
* don't ;-( */
stb->st_handler = (int) DeviceProc ((UBYTE *)fname);
stb->st_dev = (dev_t) stb->st_handler;
/* HELP! no way to reach the fib of this entry except when
* scanning the parent directory, but this is NOT acceptable ! */
stb->st_ino = 123;
/* this is the most important entry ;-) */
stb->st_mode = S_IFLNK | 0777;
stb->st_size = 1024; /* again, this should be availabe... */
stb->st_nlink = 1;
stb->st_uid = stb->st_gid = stb->st_rdev = 0;
/* again, these values ARE accessible, but only by ExNext */
stb->st_atime = stb->st_mtime = stb->st_ctime = 0;
stb->st_blksize = stb->st_blocks = 0;
goto rest_sigmask;
}
error:
syscall (SYS_sigsetmask, omask);
errno = __ioerr_to_errno (err);
KPRINTF (("ioerr = %ld, &errno = %lx, errno = %ld\n", err, &errno, errno));
return -1;
}
KPRINTF (("__stat: lock %s ok.\n",fname));
/* alloca() returns stack memory, so it's guaranteed to be word
* aligned (anything else would be deadly for the sp...) Since DOS needs
* long aligned data, we'll allocate 1 word more and adjust as needed */
fib = alloca (sizeof(*fib) + 2);
/* DON'T use LONG_ALIGN(alloca(..)), the argument is evaluated more than once! */
fib = LONG_ALIGN (fib);
info = alloca (sizeof(*info) + 2);
info = LONG_ALIGN (info);
if (!(Examine (lock, fib)))
{
__unlock (lock);
goto error;
}
stb->st_nlink = 1; /* always one link entry per file, unless... */
mode = 0L;
stb->st_amode = fib->fib_Protection;
if (!(fib->fib_Protection & FIBF_EXECUTE))
mode |= S_IXUSR;
else if (fib->fib_Protection & FIBF_SCRIPT)
mode |= S_IXUSR;
if (!(fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)))
mode |= S_IWUSR;
if (!(fib->fib_Protection & FIBF_READ))
mode |= S_IRUSR;
#ifdef FIBF_GRP_EXECUTE
/* FIBF_GRP_EXECUTE requires at least OS3 headers */
if (fib->fib_Protection & FIBF_GRP_EXECUTE)
mode |= S_IXGRP;
if ((fib->fib_Protection & (FIBF_GRP_WRITE|FIBF_GRP_DELETE)) == (FIBF_GRP_WRITE|FIBF_GRP_DELETE))
mode |= S_IWGRP;
if (fib->fib_Protection & FIBF_GRP_READ)
mode |= S_IRGRP;
if (fib->fib_Protection & FIBF_OTR_EXECUTE)
mode |= S_IXOTH;
if ((fib->fib_Protection & (FIBF_OTR_WRITE|FIBF_OTR_DELETE)) == (FIBF_OTR_WRITE|FIBF_OTR_DELETE))
mode |= S_IWOTH;
if (fib->fib_Protection & FIBF_OTR_READ)
mode |= S_IROTH;
#endif
switch (fib->fib_DirEntryType)
{
case ST_LINKDIR:
stb->st_nlink ++; /* we never get more than a link count of two.. */
case ST_ROOT:
case ST_USERDIR:
mode |= S_IFDIR;
break;
/* at the moment, we NEVER get this entry, since we can't get a lock
* on a symlink */
case ST_SOFTLINK:
mode |= S_IFLNK;
break;
case ST_LINKFILE:
stb->st_nlink ++;
case ST_FILE:
default:
mode |= S_IFREG;
}
stb->st_mode = mode;
/* support for annotated attributes (cool name ;-)) */
if (! strncmp (fib->fib_Comment, "!SP!", 4))
{
int sp_mode, sp_addr;
if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
stb->st_mode = sp_mode;
}
/* some kind of a default-size for directories... */
stb->st_size = fib->fib_DirEntryType<0 ? fib->fib_Size : 1024;
stb->st_handler = (long)((struct FileLock *)((long)lock << 2))->fl_Task;
stb->st_dev = (dev_t)stb->st_handler; /* trunc to 16 bit */
stb->st_ino = fib->fib_DiskKey;
stb->st_atime =
stb->st_ctime =
stb->st_mtime = (8*365+2)*24*3600 + ix.ix_gmt_offset +
fib->fib_Date.ds_Days * 24 * 60 * 60 +
fib->fib_Date.ds_Minute * 60 +
fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
/* in a try to count the blocks used for filemanagement, we add one for
* the fileheader. Note, that this is wrong for large files, where there
* are some extension-blocks as well */
stb->st_blocks = fib->fib_NumBlocks + 1;
bzero (info, sizeof (*info));
stb->st_blksize = 0;
if (Info(lock, info))
/* optimal for fileio is as high as possible ;-) This is a
* compromise between "as high as possible" and not too restricitve
* for people low on memory */
stb->st_blksize = info->id_BytesPerBlock * ix.ix_fs_buf_factor;
if (! stb->st_blksize) stb->st_blksize = 512;
__unlock (lock);
rest_sigmask:
syscall (SYS_sigsetmask, omask);
errno = 0;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return 0;
}
/***************************************************************************/
int
stat (char *fname, struct stat *stb)
{
return __stat (fname, stb, __lock);
}
int
lstat (char *fname, struct stat *stb)
{
return __stat (fname, stb, __llock);
}